// ------------------------------------------------------------------------------------------
// Licensed by Interprise Solutions.
// http://www.InterpriseSolutions.com
// For details on this license please visit  the product homepage at the URL above.
// THE ABOVE NOTICE MUST REMAIN INTACT.
// ------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using InterpriseSuiteEcommerceCommon;
using InterpriseSuiteEcommerceCommon.DTO;
using InterpriseSuiteEcommerceCommon.InterpriseIntegration.JSONLib;
using InterpriseSuiteEcommerceControls.Validators;
using InterpriseSuiteEcommerceControls.Validators.Special;

namespace InterpriseSuiteEcommerceControls.mobile
{
    public class AddressControl2 : CompositeControl
    {
        #region Variable Declaration

        protected const string ALIGN_ATTRIBUTE = "align";
        protected const string ALIGN_RIGHT = "right";
        protected const string ALIGN_LEFT = "left";

        private const string APPEARANCE_CATEGORY = "Address Appearance";
        private const string CAPTION_WIDTH = "CaptionWidth";
        private const string INPUT_WIDTH = "InputWidth";
        private const string STATE_TEMP = "StateTemporary";
        private const string TABLE_STYLE = "Table Style";
        private const string TABLE_CSS_CLASS = "TableClass";
        private const string SHOW_FIRST_NAME = "Show First Name";
        private const string SHOW_LAST_NAME = "Show Last Name";
        private const string SHOW_ACCOUNT_NAME = "Show Account Name";
        private const string SHOW_ADDRESSES = "ShowAddresses";
        private const string SHOW_COUNTY = "ShowCounty";
        private const string SHOW_PHONE_NUMBER = "ShowPhoneNumber";
        private const string REGISTER_COUNTRIES = "Register Countries";
        private const string SHOW_RESIDENCE_TYPE = "ShowResidenceType";

        // ERROR messages...
        protected const string VALIDATORS_CATEGORY = "Validators Category";
        private const string REQUIRED_FIRST_NAME_ERROR_MESSAGE = "RequiredFirstNameErrorMessage";
        private const string REQUIRED_LAST_NAME_ERROR_MESSAGE = "RequiredLastNameErrorMessage";
        private const string REQUIRED_ACCOUNT_NAME_ERROR_MESSAGE = "RequiredAccountNameErrorMessage";
        private const string REQUIRED_ADDRESS_ERROR_MESSAGE = "RequiredAddressErrorMessage";
        private const string REQUIRED_PHONE_ERROR_MESSAGE = "RequiredPhoneErrorMessage";

        private const string FIRST_NAME_MAXIMUM_CHARACTER_LENGTH = "FirstNameMaximumCharacterLength";
        private const string LAST_NAME_MAXIMUM_CHARACTER_LENGTH = "LastNameMaximumCharacterLength";
        private const string ACCOUNT_NAME_MAXIMUM_CHARACTER_LENGTH = "AccountNameMaximumCharacterLength";
        private const string ADDRESS_MAXIMUM_CHARACTER_LENGTH = "AddressMaximumCharacterLength";
        private const string PHONE_MAXIMUM_CHARACTER_LENGTH = "PhoneMaximumCharacterLength";

        private const string FIRST_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE = "FirstNameMaximumCharacterLengthErrorMessage";
        private const string LAST_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE = "LastNameMaximumCharacterLengthErrorMessage";
        private const string ACCOUNT_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE = "AccountNameMaximumCharacterLengthErrorMessage";
        private const string ADDRESS_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE = "AddressMaximumCharacterLengthErrorMessage";
        private const string PHONE_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE = "PhoneMaximumCharacterLengthErrorMessage";

        private const string CITY_REQUIRED_ERROR_MESSAGE = "CityRequiredErrorMessage";
        private const string CITY_MAXIMUM_CHARACTER_LENGTH = "CityMaximumCharacterLength";
        private const string CITY_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE = "CityMaximumCharacterLengthErrorMessage";

        private const string POSTAL_CODE_REQUIRED_ERROR_MESSAGE = "PostalCodeRequiredErrorMessage";
        private const string POSTAL_CODE_MAXIMUM_CHARACTER_LENGTH = "PostalCodeMaximumCharacterLength";
        private const string POSTAL_CODE_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE = "PostalCodeMaximumCharacterLengthErrorMessage";

        private const string POBOX_ADDRESS_NOT_ALLOWED_ERROR_MESSAGE = "POBoxAddressNotAllowedMessage";

        private const string ENABLE_VALIDATION = "EnableValidation";

        // -------------------------->

        private Table _template;

        private Label _lblFirstName;
        private TextBox _txtFirstName;

        private Label _lblLastName;
        private TextBox _txtLastName;

        private Label _lblAccountName;
        private TextBox _txtAccountName;

        private Label _lblCountryCaption;
        private DropDownList _cboCountry;

        private Label _lblAddressCaption;
        private TextBox _txtAddress;

        private Label _lblResidenceType;
        private DropDownList _cboResidenceType;

        // With State specific fields        
        //private Label _lblWithStateCityStatePostalCaption;
        private Label _lblWithCityCaption;
        private Label _lblWithStateCaption;
        private Label _lblWithPostalCaption;

        private TextBox _txtWithStateCity;
        public TextBox _txtWithStatePostalCode;

        private Label _lblCountyCaption;
        private TextBox _txtCounty;

        // Without State specific fields
        private Label _lblWithoutStateCityCaption;
        private TextBox _txtWithoutStateCity;

        private Label _lblWithoutStatePostalCaption;
        public TextBox _txtWithoutStatePostalCode;

        private Label _lblPhoneNumberCaption;
        private TextBox _txtPhoneNumber;

        private DropDownList _stateDropDown;
        private List<CountryAddressDTO> _countriesDTO = null;

        // Internals..
        TableRow _rowWithStateCityStatePostal;
        TableRow _rowWithoutStateCity;
        TableRow _rowWithoutStateCountyPostal;

        private TableRow WithCity;
        private TableRow WithStateCity;
        private TableRow WithState;
        private TableRow StateDropDown;
        private TableRow WithPostal;
        private TableRow WithStatePostal;

        private TableRow CountyRow;
        private TableRow CountryTextRow;

        private TableRow WithoutStateCity;
        private TableRow WithoutStateCityText;
        private TableRow WithoutStatePostalRow;
        private TableRow WithoutStatePostalCodeRow;

        private readonly string RESIDENCE_TYPE_RESIDENTIAL = ResidenceTypes.Residential.ToString();
        private readonly string RESIDENCE_TYPE_COMMERCIAL = ResidenceTypes.Commercial.ToString();

        private CountryAddressDTO _currentlySelectedCountry;
        private List<string> _postalCodeOptionalCountryCodes = new List<string>();

        private InputValidatorSummary _errorSummaryControl;
        private HtmlForm _hostForm;

        private bool _blnSameWithBillingAddress;
        private string _strBillingCountryCode;
        private string _strBillingCity;
        private string _strBillingStateCode;
        private string _strBillingPostalCode;
        private string _strBillingAddress;
        private string _strBillingPhone;
        private string _strBillingName;

        #endregion

        #region Events

        protected event EventHandler<RowEventArgs> RowAdding;
        protected event EventHandler<RowEventArgs> RowAdded;

        #endregion

        #region Constructor

        public AddressControl2()
        {

            _template = new Table();

            _lblFirstName = new Label();
            _txtFirstName = new TextBox();
            _lblLastName = new Label();
            _txtLastName = new TextBox();

            _lblAccountName = new Label();
            _txtAccountName = new TextBox();

            _lblResidenceType = new Label();
            _cboResidenceType = new DropDownList();
            _cboResidenceType.Items.Add(new ListItem(RESIDENCE_TYPE_RESIDENTIAL, RESIDENCE_TYPE_RESIDENTIAL));
            _cboResidenceType.Items.Add(new ListItem(RESIDENCE_TYPE_COMMERCIAL, RESIDENCE_TYPE_COMMERCIAL));

            _lblCountryCaption = new Label();
            _cboCountry = new DropDownList();
            _lblAddressCaption = new Label();
            _txtAddress = new TextBox();
            _txtAddress.TextMode = TextBoxMode.MultiLine;

            // With state specific fields
            _lblWithCityCaption = new Label();
            _lblWithStateCaption = new Label();
            _lblWithPostalCaption = new Label();
            _txtWithStateCity = new TextBox();
            _txtWithStatePostalCode = new TextBox();

            // Without state specific fields
            _lblWithoutStateCityCaption = new Label();
            _txtWithoutStateCity = new TextBox();

            _lblWithoutStatePostalCaption = new Label();
            _txtWithoutStatePostalCode = new TextBox();

            _lblCountyCaption = new Label();
            _txtCounty = new TextBox();

            _lblPhoneNumberCaption = new Label();
            _txtPhoneNumber = new TextBox();

            // Internals..
            _rowWithStateCityStatePostal = new TableRow();
            _rowWithoutStateCity = new TableRow();
            _rowWithoutStateCountyPostal = new TableRow();

            _stateDropDown = new DropDownList();

            AssignClientReferenceIds();
            SetDefaultCaptions();
        }

        private void AssignClientReferenceIds()
        {
            _txtFirstName.ID = "FirstName";
            _txtLastName.ID = "LastName";
            _txtAccountName.ID = "AccountName";
            _cboResidenceType.ID = "ResidenceType";
            _cboCountry.ID = "Country";
            _txtAddress.ID = "Address";

            // With state specific fields
            _lblWithCityCaption.ID = "WithCityCaption";
            _lblWithStateCaption.ID = "WithStateCaption";
            _stateDropDown.ID = "StateDropDown";
            _stateDropDown.EnableViewState = true;
            _lblWithPostalCaption.ID = "WithPostalCaption";
            _lblWithoutStateCityCaption.ID = "WithoutStateCityCaption";
            _txtWithStateCity.ID = "WithStateCity";
            _txtWithStatePostalCode.ID = "WithStatePostalCode";

            // Without state specific fields
            _lblWithoutStatePostalCaption.ID = "WithoutStatePostalCaption";
            _txtWithoutStateCity.ID = "WithoutStateCity";
            _txtWithoutStatePostalCode.ID = "WithoutStatePostalCode";
            _txtCounty.ID = "County";

            // Internals..
            _rowWithStateCityStatePostal.ID = "WithStateCityStatePostalRow";
            _rowWithoutStateCity.ID = "WithoutStateCityRow";
            _rowWithoutStateCountyPostal.ID = "WithoutStateCountyPostalRow";
            _txtPhoneNumber.ID = "Phone";
        }

        private void SetDefaultCaptions()
        {
            AddressCaption = "Address";
            ResidenceTypeCaption = "Residence Type";
            CountryCaption = "Country";
            FirstNameCaption = "FirstName";
            LastNameCaption = "Last Name";
            AccountNameCaption = "Account Name";
            PhoneNumberCaption = "Phone Number";
            WithPostalCaption = "Postal";
            WithCityCaption = "City";
            WithOutStateCityCaption = "City";
            WithStateCityStatePostalCaption = "City/State/Postal";
            CountyCaption = "County";
        }

        #endregion

        #region Properties

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string FirstNameCaption
        {
            get { return _lblFirstName.Text; }
            set 
            { 
                _lblFirstName.Text = value;
                _txtFirstName.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string LastNameCaption
        {
            get { return _lblLastName.Text; }
            set 
            { 
                _lblLastName.Text = value;
                _txtLastName.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string AccountNameCaption
        {
            get { return _lblAccountName.Text; }
            set 
            { 
                _lblAccountName.Text = value;
                _txtAccountName.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string ResidenceTypeCaption
        {
            get { return _lblResidenceType.Text; }
            set 
            { 
                _lblResidenceType.Text = value;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string PhoneNumberCaption
        {
            get { return _lblPhoneNumberCaption.Text; }
            set 
            { 
                _lblPhoneNumberCaption.Text = value;
                _txtPhoneNumber.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string CountryCaption
        {
            get { return _lblCountryCaption.Text; }
            set 
            { 
                _lblCountryCaption.Text = value;
                _txtCounty.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string AddressCaption
        {
            get { return _lblAddressCaption.Text; }
            set 
            { 
                _lblAddressCaption.Text = value;
                _txtAddress.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string WithStateCityStatePostalCaption
        {
            get { return _lblWithCityCaption.Text; }
            set 
            { 
                _lblWithCityCaption.Text = value;
                //_txtWithStatePostalCode.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string WithStateCaption
        {
            get { return _lblWithStateCaption.Text; }
            set 
            { 
                _lblWithStateCaption.Text = value;
                
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string WithCityCaption
        {
            get { return _lblWithCityCaption.Text; }
            set 
            { 
                _lblWithCityCaption.Text = value;
                _txtWithStateCity.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string WithPostalCaption
        {
            get { return _lblWithPostalCaption.Text; }
            set 
            { 
                _lblWithPostalCaption.Text = value;
                _txtWithStatePostalCode.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string CountyCaption
        {
            get { return _lblCountyCaption.Text; }
            set 
            { 
                _lblCountyCaption.Text = value; 
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string WithOutStateCityCaption
        {
            get { return _lblWithoutStateCityCaption.Text; }
            set 
            { 
                _lblWithoutStateCityCaption.Text = value;
                _txtWithoutStateCity.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string WithOutStatePostalCaption
        {
            get { return _lblWithoutStatePostalCaption.Text; }
            set 
            { 
                _lblWithoutStatePostalCaption.Text = value;
                _txtWithoutStatePostalCode.Attributes.Add("placeholder", value);
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public Unit CaptionWidth
        {
            get { return null == ViewState[CAPTION_WIDTH] ? Unit.Empty : (Unit)ViewState[CAPTION_WIDTH]; }
            set
            {
                ViewState[CAPTION_WIDTH] = value;
                this.ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public Unit InputWidth
        {
            get { return null == ViewState[INPUT_WIDTH] ? Unit.Empty : (Unit)ViewState[INPUT_WIDTH]; }
            set
            {
                ViewState[INPUT_WIDTH] = value;
                this.ChildControlsCreated = false;
            }
        }

        [Browsable(false)]
        public string FirstName
        {
            get { return _txtFirstName.Text; }
            set { _txtFirstName.Text = value; }
        }

        [Browsable(false)]
        public string LastName
        {
            get { return _txtLastName.Text; }
            set { _txtLastName.Text = value; }
        }

        [Browsable(false)]
        public string AccountName
        {
            get { return _txtAccountName.Text; }
            set { _txtAccountName.Text = value; }
        }

        [Browsable(false)]
        public string CountryCode
        {
            get
            {
                EnsureCountriesDTOIsAlreadySet();

                if (null == _cboCountry.SelectedItem) { return string.Empty; }
                return _cboCountry.SelectedValue;
            }
            set
            {
                EnsureCountriesDTOIsAlreadySet();

                try
                {
                    _cboCountry.SelectedValue = value;
                    SyncSelectedCountry(value);
                }
                catch
                {
                    _cboCountry.SelectedValue = null;
                }
            }
        }

        [Browsable(false)]
        public string Address
        {
            get { return _txtAddress.Text; }
            set { _txtAddress.Text = value; }
        }

        [Browsable(false)]
        public ResidenceTypes ResidenceType
        {
            get
            {
                if (_cboResidenceType.SelectedValue == RESIDENCE_TYPE_COMMERCIAL)
                {
                    return ResidenceTypes.Commercial;
                }
                else
                {
                    return ResidenceTypes.Residential;
                }
            }
            set
            {
                string selectedValue = RESIDENCE_TYPE_RESIDENTIAL;
                switch (value)
                {
                    case ResidenceTypes.Residential:
                        selectedValue = RESIDENCE_TYPE_RESIDENTIAL;
                        break;
                    case ResidenceTypes.Commercial:
                        selectedValue = RESIDENCE_TYPE_COMMERCIAL;
                        break;
                }

                _cboResidenceType.SelectedValue = selectedValue;
            }
        }

        [Browsable(false)]
        public string City
        {
            get
            {
                return _currentlySelectedCountry.withState ? _txtWithStateCity.Text : _txtWithoutStateCity.Text;
            }
            set
            {
                if (_currentlySelectedCountry.withState)
                {
                    _txtWithStateCity.Text = value;
                }
                else
                {
                    _txtWithoutStateCity.Text = value;
                }
            }
        }

        [Browsable(false)]
        public string State
        {
            get
            {
                if (_stateDropDown.Items.Count > 0)
                {
                    return _stateDropDown.SelectedValue;
                }
                else
                {
                    return string.Empty;
                }
            }
            set
            {
                _stateDropDown.SelectedIndex = _stateDropDown.Items.IndexOf(_stateDropDown.Items.FindByValue(value));
            }
        }

        [Browsable(false)]
        public string PostalCode
        {
            get
            {
                return _currentlySelectedCountry.withState ? _txtWithStatePostalCode.Text : _txtWithoutStatePostalCode.Text;
            }
            set
            {
                if (_currentlySelectedCountry.withState)
                {
                    _txtWithStatePostalCode.Text = value;
                }
                else
                {
                    _txtWithoutStatePostalCode.Text = value;
                }
            }
        }

        [Browsable(false)]
        public string County
        {
            get
            {
                return _txtCounty.Text;
            }
            set
            {
                _txtCounty.Text = value;
            }
        }

        [Browsable(false)]
        public string PhoneNumber
        {
            get { return _txtPhoneNumber.Text; }
            set { _txtPhoneNumber.Text = value; }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string TableClass
        {
            get { return null == ViewState[TABLE_CSS_CLASS] ? string.Empty : (string)ViewState[TABLE_CSS_CLASS]; }
            set { ViewState[TABLE_CSS_CLASS] = value; }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string TableStyle
        {
            get { return null == ViewState[TABLE_STYLE] ? string.Empty : (string)ViewState[TABLE_STYLE]; }
            set { ViewState[TABLE_STYLE] = value; }
        }

        private string StateComboBoxId
        {
            get { return this.ClientID + "_WithStateState"; }
        }

        [Browsable(false)]
        public List<CountryAddressDTO> Countries
        {
            get { return _countriesDTO; }
            set
            {
                _countriesDTO = value;
                FillCountryFromDataSource();

                _currentlySelectedCountry = _countriesDTO[0];
            }
        }

        [Browsable(false)]
        public List<string> PostalCodeOptionalCountryCodes
        {
            get { return _postalCodeOptionalCountryCodes; }
            set { _postalCodeOptionalCountryCodes = value; }
        }

        [Browsable(false)]
        public bool DisallowShippingToPOBoxes
        {
            get { return AppLogic.AppConfigBool("DisallowShippingToPOBoxes"); }
        }

        private void FillCountryFromDataSource()
        {
            if (null != _countriesDTO)
            {
                _cboCountry.DataSource = _countriesDTO;
                _cboCountry.DataTextField = "code";
                _cboCountry.DataValueField = "code";

                _cboCountry.DataBind();
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public string TextBoxWithStatePostalCodeCssClass
        {
            set { _txtWithStatePostalCode.CssClass = value; }
            get { return _txtWithStatePostalCode.CssClass; }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public TextBox TextBoxWithStatePostalCode
        {
            get { return _txtWithStatePostalCode; }
        }

        #endregion

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public bool ShowFirstName
        {
            get
            {
                object booleanValue = ViewState[SHOW_FIRST_NAME];
                if (null == booleanValue) { return true; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set
            {
                ViewState[SHOW_FIRST_NAME] = value;
                ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public bool ShowLastName
        {
            get
            {
                object booleanValue = ViewState[SHOW_LAST_NAME];
                if (null == booleanValue) { return true; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set
            {
                ViewState[SHOW_LAST_NAME] = value;

                ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public bool ShowAccountName
        {
            get
            {
                object booleanValue = ViewState[SHOW_ACCOUNT_NAME];
                if (null == booleanValue) { return true; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set
            {
                ViewState[SHOW_ACCOUNT_NAME] = value;
                ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public bool ShowAddresses
        {
            get
            {
                object booleanValue = ViewState[SHOW_ADDRESSES];
                if (null == booleanValue) { return true; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set
            {
                ViewState[SHOW_ADDRESSES] = value;
                ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public bool ShowCounty
        {
            get
            {
                object booleanValue = ViewState[SHOW_COUNTY];
                if (null == booleanValue) { return true; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set
            {
                ViewState[SHOW_COUNTY] = value;
                ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public bool ShowResidenceType
        {
            get
            {
                object booleanValue = ViewState[SHOW_RESIDENCE_TYPE];
                if (null == booleanValue) { return true; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set
            {
                ViewState[SHOW_RESIDENCE_TYPE] = value;
                ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(APPEARANCE_CATEGORY)]
        public bool ShowPhoneNumber
        {
            get
            {
                object booleanValue = ViewState[SHOW_PHONE_NUMBER];
                if (null == booleanValue) { return true; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set
            {
                ViewState[SHOW_PHONE_NUMBER] = value;
                ChildControlsCreated = false;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string LastNameRequiredErrorMessage
        {
            get
            {
                object savedValue = ViewState[REQUIRED_LAST_NAME_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[REQUIRED_LAST_NAME_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string AccountNameRequiredErrorMessage
        {
            get
            {
                object savedValue = ViewState[REQUIRED_ACCOUNT_NAME_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[REQUIRED_ACCOUNT_NAME_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string AddressRequiredErrorMessage
        {
            get
            {
                object savedValue = ViewState[REQUIRED_ADDRESS_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[REQUIRED_ADDRESS_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string PhoneRequiredErrorMessage
        {
            get
            {
                object savedValue = ViewState[REQUIRED_PHONE_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[REQUIRED_PHONE_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public int FirstNameMaximumCharacterLength
        {
            get
            {
                object savedValue = ViewState[FIRST_NAME_MAXIMUM_CHARACTER_LENGTH];

                if (null == savedValue || !(savedValue is int))
                {
                    return int.MaxValue;
                }

                return (int)savedValue;
            }
            set
            {
                ViewState[FIRST_NAME_MAXIMUM_CHARACTER_LENGTH] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public int LastNameMaximumCharacterLength
        {
            get
            {
                object savedValue = ViewState[LAST_NAME_MAXIMUM_CHARACTER_LENGTH];

                if (null == savedValue || !(savedValue is int))
                {
                    return int.MaxValue;
                }

                return (int)savedValue;
            }
            set
            {
                ViewState[LAST_NAME_MAXIMUM_CHARACTER_LENGTH] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public int AccountNameMaximumCharacterLength
        {
            get
            {
                object savedValue = ViewState[ACCOUNT_NAME_MAXIMUM_CHARACTER_LENGTH];

                if (null == savedValue || !(savedValue is int))
                {
                    return int.MaxValue;
                }

                return (int)savedValue;
            }
            set
            {
                ViewState[ACCOUNT_NAME_MAXIMUM_CHARACTER_LENGTH] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public int AddressMaximumCharacterLength
        {
            get
            {
                object savedValue = ViewState[ADDRESS_MAXIMUM_CHARACTER_LENGTH];

                if (null == savedValue || !(savedValue is int))
                {
                    return int.MaxValue;
                }

                return (int)savedValue;
            }
            set
            {
                ViewState[ADDRESS_MAXIMUM_CHARACTER_LENGTH] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public int PhoneMaximumCharacterLength
        {
            get
            {
                object savedValue = ViewState[PHONE_MAXIMUM_CHARACTER_LENGTH];

                if (null == savedValue || !(savedValue is int))
                {
                    return int.MaxValue;
                }

                return (int)savedValue;
            }
            set
            {
                ViewState[PHONE_MAXIMUM_CHARACTER_LENGTH] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string FirstNameMaximumCharacterLengthErrorMessage
        {
            get
            {
                object savedValue = ViewState[FIRST_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[FIRST_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string LastNameMaximumCharacterLengthErrorMessage
        {
            get
            {
                object savedValue = ViewState[LAST_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[LAST_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string AccountNameMaximumCharacterLengthErrorMessage
        {
            get
            {
                object savedValue = ViewState[ACCOUNT_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[ACCOUNT_NAME_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string AddressMaximumCharacterLengthErrorMessage
        {
            get
            {
                object savedValue = ViewState[ADDRESS_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[ADDRESS_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string PhoneMaximumCharacterLengthErrorMessage
        {
            get
            {
                object savedValue = ViewState[PHONE_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[PHONE_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string CityRequiredErrorMessage
        {
            get
            {
                object savedValue = ViewState[CITY_REQUIRED_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[CITY_REQUIRED_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string PostalCodeRequiredErrorMessage
        {
            get
            {
                object savedValue = ViewState[POSTAL_CODE_REQUIRED_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[POSTAL_CODE_REQUIRED_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public int CityMaximumCharacterLength
        {
            get
            {
                object savedValue = ViewState[CITY_MAXIMUM_CHARACTER_LENGTH];

                if (null == savedValue || !(savedValue is int))
                {
                    return int.MaxValue;
                }

                return (int)savedValue;
            }
            set
            {
                ViewState[CITY_MAXIMUM_CHARACTER_LENGTH] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public int PostalCodeMaximumCharacterLength
        {
            get
            {
                object savedValue = ViewState[POSTAL_CODE_MAXIMUM_CHARACTER_LENGTH];

                if (null == savedValue || !(savedValue is int))
                {
                    return int.MaxValue;
                }

                return (int)savedValue;
            }
            set
            {
                ViewState[POSTAL_CODE_MAXIMUM_CHARACTER_LENGTH] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string CityMaximumCharacterLengthErrorMessage
        {
            get
            {
                object savedValue = ViewState[CITY_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[CITY_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string PostalCodeMaximumCharacterLengthErrorMessage
        {
            get
            {
                object savedValue = ViewState[POSTAL_CODE_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[POSTAL_CODE_MAXIMUM_CHARACTER_LENGTH_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string POBoxAddressNotAllowedErrorMessage
        {
            get
            {
                object savedValue = ViewState[POBOX_ADDRESS_NOT_ALLOWED_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[POBOX_ADDRESS_NOT_ALLOWED_ERROR_MESSAGE] = value;
            }
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public DropDownList CboCountry
        {
            get
            {
                return _cboCountry;
            }
        }

        [Browsable(false)]
        public InputValidatorSummary ErrorSummaryControl
        {
            get { return _errorSummaryControl; }
            set { _errorSummaryControl = value; }
        }

        [Browsable(false)]
        public HtmlForm HostForm
        {
            get { return _hostForm; }
            set { _hostForm = value; }
        }

        [Browsable(true)]
        public bool SameWithBillingAddress
        {
            get { return _blnSameWithBillingAddress; }
            set { _blnSameWithBillingAddress = value; }
        }

        [Browsable(true)]
        public string BillingAddress
        {
            get { return _strBillingAddress; }
            set { _strBillingAddress = value; }
        }

        [Browsable(true)]
        public string BillingCountryCode
        {
            get { return _strBillingCountryCode; }
            set { _strBillingCountryCode = value; }
        }

        [Browsable(true)]
        public string BillingCity
        {
            get { return _strBillingCity; }
            set { _strBillingCity = value; }
        }

        [Browsable(true)]
        public string BillingStateCode
        {
            get { return _strBillingStateCode; }
            set { _strBillingStateCode = value; }
        }

        [Browsable(true)]
        public string BillingPostalCode
        {
            get { return _strBillingPostalCode; }
            set { _strBillingPostalCode = value; }
        }

        [Browsable(true)]
        public string BillingPhone
        {
            get { return _strBillingPhone; }
            set { _strBillingPhone = value; }
        }

        [Browsable(true)]
        public string BillingName
        {
            get { return _strBillingName; }
            set { _strBillingName = value; }
        }

        public bool RegisterCountries
        {
            get
            {
                object booleanValue = ViewState[REGISTER_COUNTRIES];
                if (null == booleanValue) { return false; }

                return booleanValue is bool && (bool)booleanValue;
            }
            set { ViewState[REGISTER_COUNTRIES] = value; }
        }

        public enum AddressRow
        {
            FirstName,
            LastName,
            AccountName,
            Country,
            AddressType,
            TaxNumber,
            Address,
            CityStatePostal,
            Phone
        }

        public class RowEventArgs : EventArgs
        {
            AddressRow _row;
            Table _template;

            public RowEventArgs(Table template, AddressRow row)
            {
                _template = template;
                _row = row;
            }

            public Table Template
            {
                get { return _template; }
            }

            public AddressRow Row
            {
                get { return _row; }
            }
        }

        protected virtual void OnRowAdding(RowEventArgs e)
        {
            if (null != RowAdding)
            {
                RowAdding(this, e);
            }
        }

        protected virtual void OnRowAdded(RowEventArgs e)
        {
            if (null != RowAdded)
            {
                RowAdded(this, e);
            }
        }

        protected Table Template
        {
            get { return _template; }
        }

        protected void AddFieldRow(Label withCaptionControl, params Control[] withInputControls)
        {
            AddFieldRow(new TableRow(), withCaptionControl, null, withInputControls);
        }

        protected void AddFieldRow(Label withCaptionControl, bool? merge, params Control[] withInputControls)
        {
            AddFieldRow(new TableRow(), withCaptionControl, merge, withInputControls);
        }

        protected void AddFieldRow(TableRow onRow, Label withCaptionControl, bool? merge, params Control[] withInputControls)
        {
            var cell = new TableCell();
            if (withCaptionControl != null)
            {
                onRow.Cells.Add(cell);
                cell.Controls.Add(withCaptionControl);
            }

            if (withInputControls.Length > 0)
            {

                if (!merge.HasValue || !merge.Value)
                {
                    cell = new TableCell();
                    onRow.Cells.Add(cell);
                }

                if (Unit.Empty != this.InputWidth) { cell.Width = this.InputWidth; }

                foreach (Control inputControl in withInputControls)
                {
                    if (inputControl is TextBox || inputControl is DropDownList)
                    {
                        cell.Controls.Add(inputControl);
                        if (!_txtWithStatePostalCode.Equals(inputControl))
                        {
                            (inputControl as WebControl).CssClass = "inputTextBox";
                        }
                    }
                    else
                    {
                        cell.Controls.Add(inputControl);
                    }
                }
            }

            _template.Rows.Add(onRow);
        }

        private void ApplyTemplateStyles()
        {
            if (!string.IsNullOrEmpty(this.TableClass))
            {
                _template.CssClass = this.TableClass;
            }

            if (!string.IsNullOrEmpty(this.TableStyle))
            {
                _template.Attributes.Add("style", this.TableStyle);
            }

            _template.Width = this.Width;
            _template.Height = this.Height;
        }

        protected override void CreateChildControls()
        {
            ApplyTemplateStyles();

            //-----------------------------------
            // Name Fields
            //-----------------------------------

            if (ShowFirstName)
            {
                OnRowAdding(new RowEventArgs(_template, AddressRow.FirstName));
                //AddFieldRow(_lblFirstName);

                AddFieldRow(null, _txtFirstName);
                OnRowAdded(new RowEventArgs(_template, AddressRow.FirstName));
            }

            if (ShowLastName)
            {
                OnRowAdding(new RowEventArgs(_template, AddressRow.LastName));
                //AddFieldRow(_lblLastName);
                AddFieldRow(null, _txtLastName);
                OnRowAdded(new RowEventArgs(_template, AddressRow.LastName));
            }

            if (ShowAccountName)
            {
                OnRowAdding(new RowEventArgs(_template, AddressRow.AccountName));
                //AddFieldRow(_lblAccountName);
                AddFieldRow(null, _txtAccountName);
                OnRowAdded(new RowEventArgs(_template, AddressRow.AccountName));
            }

            if (ShowAddresses)
            {
                //-----------------------------------
                // Country fields
                //-----------------------------------
                OnRowAdding(new RowEventArgs(_template, AddressRow.Country));
                //AddFieldRow(_lblCountryCaption);
                AddFieldRow(null, _cboCountry);
                OnRowAdded(new RowEventArgs(_template, AddressRow.Country));

                _txtAddress.CssClass = "AddressControlTextArea";
                _txtAddress.Rows = 4;

                OnRowAdding(new RowEventArgs(_template, AddressRow.Address));
                //AddFieldRow(_lblAddressCaption);
                AddFieldRow(null, _txtAddress);
                OnRowAdded(new RowEventArgs(_template, AddressRow.Address));

                if (ShowResidenceType)
                {
                    OnRowAdding(new RowEventArgs(_template, AddressRow.AddressType));
                    //AddFieldRow(_lblResidenceType);
                    AddFieldRow(null, _cboResidenceType);
                    OnRowAdded(new RowEventArgs(_template, AddressRow.AddressType));
                }

                OnRowAdding(new RowEventArgs(_template, AddressRow.CityStatePostal));
                //WithCity = new TableRow { ID = "row_" + _lblWithCityCaption.ID };
                //AddFieldRow(WithCity, _lblWithCityCaption, false);

                StateDropDown = new TableRow { ID = "row_" + _stateDropDown.ID };
                AddFieldRow(StateDropDown, null, null, _stateDropDown);

                WithStatePostal = new TableRow { ID = "row_" + _txtWithStatePostalCode.ID };
                AddFieldRow(WithStatePostal, null, null, _txtWithStatePostalCode);

                WithStateCity = new TableRow { ID = "row_" + _txtWithStateCity.ID };
                AddFieldRow(WithStateCity, null, null, _txtWithStateCity);

                //WithState = new TableRow { ID = "row_" + _lblWithStateCaption.ID };
                //AddFieldRow(WithState, _lblWithStateCaption, false);

                //WithPostal = new TableRow { ID = "row_" + _lblWithPostalCaption.ID };
                //AddFieldRow(WithPostal, _lblWithPostalCaption, false);

                //WithoutStateCity = new TableRow { ID = "row_" + _lblWithoutStateCityCaption.ID };
                //AddFieldRow(WithoutStateCity, _lblWithoutStateCityCaption, false);

                WithoutStateCityText = new TableRow { ID = "row_" + _txtWithoutStateCity.ID };
                AddFieldRow(WithoutStateCityText, null, null, _txtWithoutStateCity);

                if (ShowCounty)
                {
                    //CountyRow = new TableRow { ID = "row_" + _lblCountyCaption.ID };
                    //AddFieldRow(CountyRow, _lblCountyCaption, false);

                    CountryTextRow = new TableRow { ID = "row_" + _txtCounty.ID };
                    AddFieldRow(CountryTextRow, null, null, _txtCounty);
                }

                //WithoutStatePostalRow = new TableRow { ID = "row_" + _lblWithoutStatePostalCaption.ID };
                //AddFieldRow(WithoutStatePostalRow, _lblWithoutStatePostalCaption, null);

                WithoutStatePostalCodeRow = new TableRow { ID = "row_" + _txtWithoutStatePostalCode.ID };
                AddFieldRow(WithoutStatePostalCodeRow, null, null, _txtWithoutStatePostalCode);
                OnRowAdded(new RowEventArgs(_template, AddressRow.CityStatePostal));
            }
            //--------------------------> 

            //-----------------------------------
            // Phone Number Fields
            ////-----------------------------------
            //AddFieldRow(_lblPhoneNumberCaption);
            //OnRowAdding(new RowEventArgs(_template, AddressRow.Phone));

            AddFieldRow(null, _txtPhoneNumber);
            OnRowAdded(new RowEventArgs(_template, AddressRow.Phone));
            //------------------------>            

            this.Controls.Add(_template);

            // We need to participate in the page validation
            // for validators that require server-side specific logic...
            if (this.Visible)
            {
                this.AttachValidators();
            }
        }

        private void AttachValidators()
        {
            List<InputValidator> defaultValidators = this.ProvideValidators();
            AttachValidators(defaultValidators);

            if (this.ShowAddresses)
            {
                List<InputValidator> withStateValidators = this.GetWithStateValidators();
                List<InputValidator> withOutStateValidators = this.GetWithoutStateValidators();

                AttachValidators(withStateValidators);
                AttachValidators(withOutStateValidators);

                //Postal Code Validators
                InputLengthValidator withStatePostalCodInputeRangeCheck = new InputLengthValidator(_txtWithStatePostalCode, this.PostalCodeMaximumCharacterLength, this.PostalCodeMaximumCharacterLengthErrorMessage);
                withStatePostalCodInputeRangeCheck.Evaluate += PostalCodeWithState_Evaluate;
                withStatePostalCodInputeRangeCheck.EnableClientSideValidation = false;
                HandleValidationErrorEvent(withStatePostalCodInputeRangeCheck);

                RequiredInputValidator withStatePostalCodeRequired = new RequiredInputValidator(_txtWithStatePostalCode, this.PostalCodeRequiredErrorMessage, withStatePostalCodInputeRangeCheck);
                withStatePostalCodeRequired.Evaluate += PostalCodeWithState_Evaluate;
                withStatePostalCodeRequired.EnableClientSideValidation = false;
                HandleValidationErrorEvent(withStatePostalCodeRequired);
                this.Controls.Add(withStatePostalCodeRequired);

                InputLengthValidator withoutStatePostalCodeInputRangeCheck = new InputLengthValidator(_txtWithoutStatePostalCode, this.PostalCodeMaximumCharacterLength, this.PostalCodeMaximumCharacterLengthErrorMessage);
                withoutStatePostalCodeInputRangeCheck.Evaluate += PostalCodeWithoutState_Evaluate;
                withoutStatePostalCodeInputRangeCheck.EnableClientSideValidation = false;
                HandleValidationErrorEvent(withoutStatePostalCodeInputRangeCheck);

                RequiredInputValidator withoutStatePostalCodeRequired = new RequiredInputValidator(_txtWithoutStatePostalCode, this.PostalCodeRequiredErrorMessage, withoutStatePostalCodeInputRangeCheck);
                withoutStatePostalCodeRequired.Evaluate += PostalCodeWithoutState_Evaluate;
                withoutStatePostalCodeRequired.EnableClientSideValidation = false;
                HandleValidationErrorEvent(withoutStatePostalCodeRequired);
                this.Controls.Add(withoutStatePostalCodeRequired);
            }
        }

        private void AttachValidators(List<InputValidator> validatorsToAttach)
        {
            foreach (InputValidator validator in validatorsToAttach)
            {
                this.Controls.Add(validator);
            }
        }

        private void SyncSelectedCountry(string withCountryCode)
        {
            if (!CommonLogic.IsStringNullOrEmpty(withCountryCode))
            {
                _currentlySelectedCountry = FindSelectedCountry(withCountryCode);
                if (null == _currentlySelectedCountry)
                {
                    throw new InvalidOperationException("Current Country not in sync!!!");
                }
            }
        }

        private CountryAddressDTO FindSelectedCountry(string usingCode)
        {
            if (null != this._countriesDTO)
            {
                var foundMatch = _countriesDTO.Find(c => { return c.code == usingCode; });
                if (foundMatch == null)
                {
                    foundMatch = CountryAddressDTO.Find(usingCode);
                }

                return foundMatch;
            }

            return null;
        }

        private void ToggleRowVisibilityBasedOnSelectedCountry()
        {
            if (!this.ShowAddresses || null == _currentlySelectedCountry) return;

            if (_currentlySelectedCountry.withState)
            {
                //WithCity.Style["display"] = "";
                //WithStateCity.Style["display"] = "";
                //WithState.Style["display"] = "";
                StateDropDown.Style["display"] = "";
                //WithPostal.Style["display"] = "";
                //WithStatePostal.Style["display"] = "";

                //WithoutStateCity.Style["display"] = "none";
                WithoutStateCityText.Style["display"] = "none";
                //WithoutStatePostalRow.Style["display"] = "none";
                WithoutStatePostalCodeRow.Style["display"] = "none";

                _rowWithStateCityStatePostal.Style["display"] = "";
                _rowWithoutStateCity.Style["display"] = "none";
                _rowWithoutStateCountyPostal.Style["display"] = "none";
            }
            else
            {
                //WithCity.Style["display"] = "none";
                //WithStateCity.Style["display"] = "none";
                //WithState.Style["display"] = "none";
                StateDropDown.Style["display"] = "none";
                //WithPostal.Style["display"] = "none";
                //WithStatePostal.Style["display"] = "none";

                //WithoutStateCity.Style["display"] = "";
                WithoutStateCityText.Style["display"] = "";
                //WithoutStatePostalRow.Style["display"] = "";
                WithoutStatePostalCodeRow.Style["display"] = "";
                _rowWithoutStateCity.Style["display"] = "";
                _rowWithoutStateCountyPostal.Style["display"] = "";
                _rowWithStateCityStatePostal.Style["display"] = "none";
            }
        }

        public override void DataBind()
        {
            base.DataBind();
            RenderStateDropDownBasedOnCurrentSelectedCountry();
        }

        public void RenderStateDropDownBasedOnCurrentSelectedCountry()
        {
            //buffer.AppendFormat("<select name=\"{0}\" id=\"{0}\" >\n", this.StateComboBoxId);

            string selectedState = this.State;
            _stateDropDown.ID = this.StateComboBoxId;
            if (_currentlySelectedCountry.withState)
            {
                var states = _currentlySelectedCountry.GetStates();
                _stateDropDown.Items.AddRange(
                              (
                                from state in states
                                select new ListItem { 
                                    Value = state.code, 
                                    Text = state.code + " - " + state.description, 
                                    Selected = (state.code == selectedState)? true : false }).ToArray()
                              );

                //if (states.Count > 0)
                //{
                //    foreach (StateDTO state in states)
                //    {
                //        buffer.AppendFormat(
                //            "<option {0} value=\"{1}\" >{2}</option>",
                //            selectedState.Equals(state.code) ? "selected=\"selected\"" : string.Empty,
                //            Security.HtmlEncode(state.code),
                //            Security.HtmlEncode(string.Format("{0} - {1}", state.code, state.description))
                //        );
                //    }
                //}
                //else
                //{
                //    buffer.Append("<option selected=\"selected\" value=\"\" >None</option>");
                //}
            }

            //buffer.Append("</select>");
            //_stateDropDown.Text = buffer.ToString();
        }

        private void EnsureCountriesDTOIsAlreadySet()
        {
            if (!this.DesignMode && this.ShowAddresses)
            {
                if (null == _countriesDTO || _countriesDTO.Count == 0)
                {
                    throw new ArgumentException("Countries not set!!!");
                }
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            try
            {
                base.Render(writer);
            }
            catch (Exception ex)
            {
                writer.WriteLine(Security.HtmlEncode(ex.Message));
                writer.WriteLine(Security.HtmlEncode(ex.StackTrace));
            }
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            EnsureCountriesDTOIsAlreadySet();

            if (!this.DesignMode)
            {
                ToggleRowVisibilityBasedOnSelectedCountry();

                var script = new StringBuilder();

                script.Append("<script type=\"text/javascript\" language=\"Javascript\" >\n");
                script.Append("$(document).ready(function() {\n");
                script.AppendFormat("    ise.StringResource.registerString('createaccount.aspx.29', '{0}');\n", AppLogic.GetString("createaccount.aspx.29", Customer.Current.SkinID, Customer.Current.LocaleSetting));
                script.AppendFormat("    ise.StringResource.registerString('createaccount.aspx.30', '{0}');\n", AppLogic.GetString("createaccount.aspx.30", Customer.Current.SkinID, Customer.Current.LocaleSetting));
                script.AppendFormat("    ise.StringResource.registerString('createaccount.aspx.31', '{0}');\n", AppLogic.GetString("createaccount.aspx.31", Customer.Current.SkinID, Customer.Current.LocaleSetting));
                script.AppendFormat("    ise.StringResource.registerString('createaccount.aspx.77', '{0}');\n", AppLogic.GetString("createaccount.aspx.77", Customer.Current.SkinID, Customer.Current.LocaleSetting));
                script.AppendFormat(" var control = ise.Controls.AddressController.registerControl('{0}');\n", this.ClientID);
                script.AppendLine();

                if (this.ShowAddresses && this.RegisterCountries && null != _countriesDTO)
                {
                    var serializer = new JSONSerializer(SerializeOption.All);
                    string serialized = serializer.SerializeArray(_countriesDTO);

                    script.AppendFormat(" ise.Controls.CountryRepository.setCountries({0});\n", serialized);
                    script.AppendLine();
                }

                if (null != this.ErrorSummaryControl)
                {
                    script.AppendFormat("  control.setValidationSummary({0});", this.ErrorSummaryControl.RenderInitialization());
                    script.AppendLine();
                }

                // set the required postal code countries
                if (this.PostalCodeOptionalCountryCodes.Count > 0)
                {
                    var ser = new JSONSerializer(SerializeOption.Fields);
                    string optionalCountriesAsJSArray = ser.SerializeArray(this.PostalCodeOptionalCountryCodes);
                    script.AppendFormat("  control.setPostalCodeOptionalCountries({0});\n", optionalCountriesAsJSArray);
                }

                var validators = this.ProvideValidators();
                foreach (var validator in validators)
                {
                    if (validator.SupportsClientSideValidation && validator.EnableClientSideValidation)
                    {
                        script.AppendFormat("  control.registerValidator({0});", validator.RenderInitialization());
                        script.AppendLine();
                    }
                }

                // render Validator client side evaluation CancelEventHandler
                script.Append("  var evaluateWithState = function(){ return control.getValue().withState; }; ");
                script.AppendLine();
                script.Append("  var evaluateWithOutState = function(){ return !control.getValue().withState; }; ");
                script.AppendLine();

                var withStateValidators = this.GetWithStateValidators();
                var withOutStateValidators = this.GetWithoutStateValidators();

                for (int ctr = 1; ctr <= withStateValidators.Count; ctr++)
                {
                    var current = withStateValidators[ctr - 1];
                    script.AppendFormat("  var val_{0} = {1};", ctr, current.RenderInitialization());
                    script.AppendLine();
                    script.AppendFormat("  val_{0}.setEvaluationDelegate(evaluateWithState);", ctr);
                    script.AppendLine();
                    script.AppendFormat("  control.registerValidator(val_{0});", ctr);
                    script.AppendLine();
                }

                for (int ctr = 1; ctr <= withOutStateValidators.Count; ctr++)
                {
                    var current = withOutStateValidators[ctr - 1];
                    script.AppendFormat("  var val_{0} = {1};", ctr, current.RenderInitialization());
                    script.AppendLine();
                    script.AppendFormat("  val_{0}.setEvaluationDelegate(evaluateWithOutState);", ctr);
                    script.AppendLine();
                    script.AppendFormat("  control.registerValidator(val_{0});", ctr);
                    script.AppendLine();
                }

                // NOTE:
                // Ruling of Postal Code Validation will be handled here...

                var withStatePostalCodeRequired = new RequiredInputValidator(_txtWithStatePostalCode, this.PostalCodeRequiredErrorMessage);
                withStatePostalCodeRequired.EnableClientSideValidation = false;
                var withStatePostalCodInputeRangeCheck = new InputLengthValidator(_txtWithStatePostalCode, this.PostalCodeMaximumCharacterLength, this.PostalCodeMaximumCharacterLengthErrorMessage);
                withStatePostalCodInputeRangeCheck.EnableClientSideValidation = false;

                var withoutStatePostalCodeRequired = new RequiredInputValidator(_txtWithoutStatePostalCode, this.PostalCodeRequiredErrorMessage);
                withoutStatePostalCodeRequired.EnableClientSideValidation = false;

                var withoutStatePostalCodeInputRangeCheck = new InputLengthValidator(_txtWithoutStatePostalCode, this.PostalCodeMaximumCharacterLength, this.PostalCodeMaximumCharacterLengthErrorMessage);
                withoutStatePostalCodeInputRangeCheck.EnableClientSideValidation = false;

                // Add evaluation hook on postal code.
                // We won't be validating if we have countries with optional postal codes
                script.Append("  var evaluatePostalCodeChecking = function(){ return !control.getIsPostalCodeOptional(); };\n");

                script.Append("  var postalCodeWithStateEvaluationDelegate = function(){return evaluateWithState() && evaluatePostalCodeChecking()};\n");
                script.Append("  var postalCodeWithoutStateEvaluationDelegate = function(){return evaluateWithOutState() && evaluatePostalCodeChecking()};\n");

                script.AppendFormat("  var requirePostalCodeWithState = {0};\n", withStatePostalCodeRequired.RenderInitialization());
                script.AppendFormat("  var inputCheckPostalCodeWithState = {0};\n", withStatePostalCodInputeRangeCheck.RenderInitialization());
                script.AppendFormat("  requirePostalCodeWithState.setEvaluationDelegate(postalCodeWithStateEvaluationDelegate);\n");
                script.AppendFormat("  inputCheckPostalCodeWithState.setEvaluationDelegate(postalCodeWithStateEvaluationDelegate);\n");
                script.AppendFormat("  control.registerValidator(requirePostalCodeWithState);\n");
                script.AppendFormat("  control.registerValidator(inputCheckPostalCodeWithState);\n");

                script.AppendFormat("  var requirePostalCodeWithoutState = {0};\n", withoutStatePostalCodeRequired.RenderInitialization());
                script.AppendFormat("  var inputCheckPostalCodeWithoutState = {0};\n", withoutStatePostalCodeInputRangeCheck.RenderInitialization());
                script.AppendFormat("  requirePostalCodeWithoutState.setEvaluationDelegate(postalCodeWithoutStateEvaluationDelegate);\n");
                script.AppendFormat("  inputCheckPostalCodeWithoutState.setEvaluationDelegate(postalCodeWithoutStateEvaluationDelegate);\n");
                script.AppendFormat("  control.registerValidator(requirePostalCodeWithoutState);\n");
                script.AppendFormat("  control.registerValidator(inputCheckPostalCodeWithoutState);\n");

                script.Append(" }\n");
                script.Append(");\n");
                script.Append("</script>\n");

                writer.Write(script.ToString());
            }

            base.RenderControl(writer);
        }

        public virtual void SetAddressDisplay(Address displayAddress)
        {
            this.FirstName = displayAddress.FirstName;
            this.LastName = displayAddress.LastName;
            this.AccountName = displayAddress.Company;
            this.ResidenceType = displayAddress.ResidenceType;
            this.Address = displayAddress.Address1;
            this.City = displayAddress.City;
            this.State = displayAddress.State;
            this.CountryCode = displayAddress.Country;
            this.County = displayAddress.County;
            this.PostalCode = displayAddress.PostalCode;
        }

        public virtual Address ExtractAddress(Customer withAssociatedCustomer, AddressTypes usingType)
        {
            var thisAddress = InterpriseSuiteEcommerceCommon.Address.New(withAssociatedCustomer, usingType);

            thisAddress.FirstName = this.FirstName;
            thisAddress.LastName = this.LastName;
            thisAddress.Company = this.AccountName;
            thisAddress.Name = this.FirstName + " " + this.LastName;
            thisAddress.ResidenceType = this.ResidenceType;
            thisAddress.Address1 = this.Address;
            thisAddress.City = this.City;
            thisAddress.State = this.State;
            thisAddress.Country = this.CountryCode;
            thisAddress.County = this.County;
            thisAddress.PostalCode = this.PostalCode;
            thisAddress.Phone = this.PhoneNumber;

            return thisAddress;
        }

        [Browsable(true), Category(VALIDATORS_CATEGORY)]
        public string FirstNameRequiredErrorMessage
        {
            get
            {
                object savedValue = ViewState[REQUIRED_FIRST_NAME_ERROR_MESSAGE];
                if (null == savedValue) { return string.Empty; }

                return savedValue.ToString();
            }
            set
            {
                ViewState[REQUIRED_FIRST_NAME_ERROR_MESSAGE] = value;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            if (Page.IsPostBack)
            {
                if (this.ShowAddresses && null != _countriesDTO)
                {
                    // resync after loading viewstate...
                    if (!this.SameWithBillingAddress)
                        SyncSelectedCountry(this.CountryCode);
                    else
                    {
                        SyncSelectedCountry(this.BillingCountryCode);
                        this.Address = this.BillingAddress;
                        this.State = this.BillingStateCode;
                        this.City = this.BillingCity;
                        this.PhoneNumber = this.BillingPhone;
                        this.PostalCode = this.BillingPostalCode;
                        this.CountryCode = this.BillingCountryCode;
                        this.AccountName = this.BillingName;
                    }
                }
            }
            base.OnLoad(e);
        }

        protected virtual List<InputValidator> ProvideValidators()
        {
            var defaultValidators = new List<InputValidator>();

            if (this.ShowFirstName)
            {
                defaultValidators.Add(
                    MakeRequiredInputValidator(
                        _txtFirstName,
                        this.FirstNameRequiredErrorMessage,
                        MakeInputLengthValidator(_txtFirstName, this.FirstNameMaximumCharacterLength, this.FirstNameMaximumCharacterLengthErrorMessage)
                    )
                );
            }

            if (this.ShowLastName)
            {
                defaultValidators.Add(
                    MakeRequiredInputValidator(
                        _txtLastName,
                        this.LastNameRequiredErrorMessage,
                        MakeInputLengthValidator(_txtLastName, this.LastNameMaximumCharacterLength, this.LastNameMaximumCharacterLengthErrorMessage)
                    )
                );
            }

            if (this.ShowAccountName)
            {
                defaultValidators.Add(
                    MakeRequiredInputValidator(
                        _txtAccountName,
                        this.AccountNameRequiredErrorMessage,
                        MakeInputLengthValidator(_txtAccountName, this.AccountNameMaximumCharacterLength, this.AccountNameMaximumCharacterLengthErrorMessage)
                    )
                );
            }

            if (this.ShowAddresses)
            {
                defaultValidators.Add(
                    MakeRequiredInputValidator(
                        _txtAddress,
                        this.AddressRequiredErrorMessage,
                        MakeInputLengthValidator(_txtAddress, this.AddressMaximumCharacterLength, this.AddressMaximumCharacterLengthErrorMessage)
                    )
                );

                if (this.DisallowShippingToPOBoxes)
                {
                    defaultValidators.Add(
                        new DisallowShippingToPOBoxesValidator(
                        _txtAddress,
                        this.POBoxAddressNotAllowedErrorMessage
                        )
                    );
                }
            }

            if (this.ShowPhoneNumber)
            {
                defaultValidators.Add(
                    MakeRequiredInputValidator(
                        _txtPhoneNumber,
                        this.PhoneRequiredErrorMessage,
                        MakeInputLengthValidator(_txtPhoneNumber, this.PhoneMaximumCharacterLength, this.PhoneMaximumCharacterLengthErrorMessage)
                    )
                );
            }

            return defaultValidators;
        }

        private List<InputValidator> GetWithStateValidators()
        {
            var withStateValidators = new List<InputValidator>();

            // validators with special case..
            // With State Fields
            var withStateCityRequired = new RequiredInputValidator(_txtWithStateCity, this.CityRequiredErrorMessage);
            withStateCityRequired.Evaluate += AddressFieldsWithState_Evaluate;
            withStateCityRequired.EnableClientSideValidation = false;
            HandleValidationErrorEvent(withStateCityRequired);
            withStateValidators.Add(withStateCityRequired);

            var withStateCityInputRangeCheck = new InputLengthValidator(_txtWithStateCity, this.CityMaximumCharacterLength, this.CityMaximumCharacterLengthErrorMessage);
            withStateCityInputRangeCheck.Evaluate += AddressFieldsWithState_Evaluate;
            withStateCityInputRangeCheck.EnableClientSideValidation = false;
            HandleValidationErrorEvent(withStateCityInputRangeCheck);
            withStateValidators.Add(withStateCityInputRangeCheck);

            return withStateValidators;
        }

        private List<InputValidator> GetWithoutStateValidators()
        {
            var withOutStateValidators = new List<InputValidator>();

            // Without State Fields
            var withoutStateCityRequired = new RequiredInputValidator(_txtWithoutStateCity, this.CityRequiredErrorMessage);
            withoutStateCityRequired.Evaluate += AddressFieldsWithoutState_Evaluate;
            withoutStateCityRequired.EnableClientSideValidation = false;
            HandleValidationErrorEvent(withoutStateCityRequired);
            withOutStateValidators.Add(withoutStateCityRequired);

            var withoutStateCityInputRangeCheck = new InputLengthValidator(_txtWithoutStateCity, this.CityMaximumCharacterLength, this.CityMaximumCharacterLengthErrorMessage);
            withoutStateCityInputRangeCheck.Evaluate += AddressFieldsWithoutState_Evaluate;
            withoutStateCityInputRangeCheck.EnableClientSideValidation = false;
            HandleValidationErrorEvent(withoutStateCityInputRangeCheck);
            withOutStateValidators.Add(withoutStateCityInputRangeCheck);

            return withOutStateValidators;
        }

        protected void AddressFieldsWithState_Evaluate(object sender, CancelEventArgs e)
        {
            e.Cancel = !_currentlySelectedCountry.withState;
        }

        protected void AddressFieldsWithoutState_Evaluate(object sender, CancelEventArgs e)
        {
            e.Cancel = _currentlySelectedCountry.withState;
        }

        private bool IsPostalCodeOptional()
        {
            foreach (string postalCodeOptionalCountry in this.PostalCodeOptionalCountryCodes)
            {
                if (postalCodeOptionalCountry == this.CountryCode)
                {
                    return true;
                }
            }

            return false;
        }

        protected void PostalCodeWithState_Evaluate(object sender, CancelEventArgs e)
        {
            AddressFieldsWithState_Evaluate(sender, e);
            if (!e.Cancel)
            {
                e.Cancel = IsPostalCodeOptional();
            }
        }

        protected void PostalCodeWithoutState_Evaluate(object sender, CancelEventArgs e)
        {
            AddressFieldsWithoutState_Evaluate(sender, e);
            if (!e.Cancel)
            {
                e.Cancel = IsPostalCodeOptional();
            }
        }

        #region AssignErrorSummaryControl

        protected virtual void HandleValidationErrorEvent(InputValidator validator)
        {
            if (null != this.ErrorSummaryControl)
            {
                validator.Error += this.ErrorSummaryControl.HandleValidationErrorEvent;
            }
        }

        #endregion

        #region MakeRequiredFieldValidator

        protected RequiredInputValidator MakeRequiredInputValidator(TextBox forControl, string withErrorMessage)
        {
            return MakeRequiredInputValidator(forControl, withErrorMessage, null);
        }

        protected RequiredInputValidator MakeRequiredInputValidator(TextBox forControl, string withErrorMessage, InputValidator next)
        {
            var validator = new RequiredInputValidator(forControl, withErrorMessage, next);
            HandleValidationErrorEvent(validator);

            return validator;
        }

        #endregion

        #region MakeCompareFieldValidator

        protected CompareInputValidator MakeCompareInputValidator(TextBox forControl, TextBox compareWithControl, string withErrorMessage)
        {
            return MakeCompareInputValidator(forControl, compareWithControl, withErrorMessage, null);
        }

        protected CompareInputValidator MakeCompareInputValidator(TextBox forControl, TextBox compareWithControl, string withErrorMessage, InputValidator next)
        {
            CompareInputValidator validator = new CompareInputValidator(forControl, compareWithControl, withErrorMessage, next);
            HandleValidationErrorEvent(validator);

            return validator;
        }

        #endregion

        #region MakeInputLengthValidator

        protected InputLengthValidator MakeInputLengthValidator(TextBox forControl, int withMaxLength, string withErrorMessage)
        {
            return MakeInputLengthValidator(forControl, InputLengthValidator.NoMinLengthFilter, withMaxLength, withErrorMessage);
        }

        protected InputLengthValidator MakeInputLengthValidator(TextBox forControl, int withMinLength, int withMaxLength, string withErrorMessage)
        {
            return MakeInputLengthValidator(forControl, withMinLength, withMaxLength, withErrorMessage, null);
        }

        protected InputLengthValidator MakeInputLengthValidator(TextBox forControl, int withMinLength, int withMaxLength, string withErrorMessage, InputValidator next)
        {
            InputLengthValidator validator = new InputLengthValidator(forControl, withMinLength, withMaxLength, withErrorMessage, next);
            HandleValidationErrorEvent(validator);

            return validator;
        }

        #endregion

        #region MakeRegularExpressionValidator

        protected RegularExpressionInputValidator MakeRegularExpressionInputValidator(TextBox forControl, string withRegularExpressionToMatchWith, string withErrorMessage)
        {
            return MakeRegularExpressionInputValidator(forControl, withRegularExpressionToMatchWith, withErrorMessage, null);
        }

        protected RegularExpressionInputValidator MakeRegularExpressionInputValidator(TextBox forControl, string withRegularExpressionToMatchWith, string withErrorMessage, InputValidator next)
        {
            RegularExpressionInputValidator validator = new RegularExpressionInputValidator(forControl, withRegularExpressionToMatchWith, withErrorMessage, next);
            HandleValidationErrorEvent(validator);

            return validator;
        }

        #endregion

    }

}

